{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "f96003c3",
   "metadata": {},
   "source": [
    "# Flip-Chip Devices in Qiskit Metal\n",
    "\n",
    "In this notebook, we will construct a device made of a coupled qubit - resonator system in a flip-chip environment. After that, we proceed to analyse them using the EPR technique available in the qiskit metal analyses folder.\n",
    "\n",
    "The flip-chip device in this notebook is very basic, consisting of two chips separated by a specific distance (that we shall specify later). There are different layout flavours, one way is to place the resonator at the 'bottom' chip or so-called 'control' chip, and the qubit on the 'top' chip or so-called 'qubit' chip.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1ea0705e",
   "metadata": {},
   "source": [
    "## 1. Building a Flip-Chip Device Design\n",
    "We use another class called the <code>DesignFlipChip</code> class. The design workflow is very similar to the one for building planar devices (cf. <code>DesignPlanar</code>), except that there are two chips, and you need to specify which chip you want to draw the device on. At the moment, the two chips are called the 'C_chip' and the 'Q_chip'."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "0d41a1db",
   "metadata": {},
   "outputs": [],
   "source": [
    "%reload_ext autoreload\n",
    "%autoreload 2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1c02013c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import qiskit_metal as metal\n",
    "from qiskit_metal import designs, draw\n",
    "from qiskit_metal import MetalGUI, Dict, Headings\n",
    "from qiskit_metal.qlibrary.qubits.transmon_cross import TransmonCross\n",
    "from qiskit_metal.qlibrary.resonator.readoutres_fc import ReadoutResFC\n",
    "\n",
    "# suppress deprecation warnings\n",
    "import warnings\n",
    "warnings.filterwarnings(\"ignore\", category=Warning)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "88f78db4",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Initialise design\n",
    "design = designs.DesignFlipChip()\n",
    "# Specify design name\n",
    "design.metadata['design_name'] = 'FlipChip_Device'\n",
    "# launch GUI\n",
    "gui = MetalGUI(design)\n",
    "# Allow running the same cell here multiple times to overwrite changes\n",
    "design.overwrite_enabled = True"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a689d06b",
   "metadata": {},
   "source": [
    "Next, we draw an Xmon on the Q-chip, and a readout resonator on the C-chip."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1a4c6ad6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# delete existing components\n",
    "design.delete_all_components()\n",
    "\n",
    "# draw an Xmon on the Q_chip. Notice that I have defined one more item called chip and set it to be the 'Q_chip'\n",
    "options_cpads = Dict(\n",
    "        connector_type = '0', # claw type\n",
    "        claw_length = '30um',\n",
    "        ground_spacing = '5um',\n",
    "        claw_width = '10um',\n",
    "        claw_gap = '6um')\n",
    "options = Dict(\n",
    "    chip = 'Q_chip',\n",
    "    cross_width = '20um',\n",
    "    cross_length = '150um',\n",
    "    cross_gap = '20um',\n",
    "    connection_pads = Dict(\n",
    "        claw_west = Dict(connector_location= '180', **options_cpads)))\n",
    "\n",
    "# position the center of the Xmon at (0,0)\n",
    "q1_x = '0.0 mm'\n",
    "q1_y = '0.0 mm'\n",
    "\n",
    "# build the device, positioned at (q1_x, q1_y)\n",
    "q1 = TransmonCross(design, 'Q1', options = Dict(pos_x=q1_x, pos_y=q1_y, **options))\n",
    "\n",
    "# rebuild in gui\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ddbc50d8",
   "metadata": {},
   "outputs": [],
   "source": [
    "# draw a readout resonator on the C_chip. Note that we specify the chip='C_chip'.\n",
    "# The readout resonator can me made into any shape. Here I opted to use a lambda/4 cpw-based resonator.\n",
    "# The open-ended end of the resonator has a circular shape with a radius of readout_radius. Change this radius to change the qubit-resonator coupling strength.\n",
    "# The cpw_width and cpw_gap are the size of the signal line and the ground gap of the cpw transmission line.\n",
    "# The parameters readout_l1 ... l5, are the lengths of various parts of the cpw.\n",
    "# arc_step is the length of a line that approximates an arc. \n",
    "options = Dict(\n",
    "    chip = 'C_chip',\n",
    "    readout_radius = '20 um',\n",
    "    readout_cpw_width = '10 um',\n",
    "    readout_cpw_gap = '10 um',\n",
    "    readout_cpw_turnradius = '50 um',\n",
    "    readout_l1 = '600 um',\n",
    "    readout_l2 = '200 um',\n",
    "    readout_l3 = '300 um',\n",
    "    readout_l4 = '150 um',\n",
    "    readout_l5 = '550 um',\n",
    "    arc_step = '5 um')\n",
    "\n",
    "# the resonator is set to have its origin at the center of the circular patch.\n",
    "# So we set the qubit and the resonator to share the same coordinate (q1_x, q1_y)\n",
    "r1 = ReadoutResFC(design, 'R1', options = Dict(pos_x = q1_x, pos_y = q1_y, **options))\n",
    "\n",
    "# rebuild in gui\n",
    "gui.rebuild()\n",
    "gui.autoscale()\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "17affa51",
   "metadata": {},
   "source": [
    "## 2. Preparation Prior to Rendering in ANSYS\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1678915d",
   "metadata": {},
   "source": [
    "As described before, we have specified two chips in the <code>FlipChipDesign</code> class, i.e. C_chip and Q_chip. This information is stored in the chips variables. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b35cb7f9",
   "metadata": {},
   "outputs": [],
   "source": [
    "design.chips"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3d7929e4",
   "metadata": {},
   "source": [
    "It is important to note that in terms of component rendering in ANSYS, the components are drawn on an XY plane with its Z-coordinate being defined by 'center_z'. For the design object we just created, C_chip components are drawn at z=0, and the Q_chip components are drawn at 20 um."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "f566f85f",
   "metadata": {},
   "outputs": [],
   "source": [
    "design.chips['C_chip']['size']['center_z']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "9007cb94",
   "metadata": {},
   "outputs": [],
   "source": [
    "design.chips['Q_chip']['size']['center_z']"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a05eeba7",
   "metadata": {},
   "source": [
    "Next, we set the Q_chip to be at a distance of, say 10 um, from the C_chip."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "dd6060f0",
   "metadata": {},
   "outputs": [],
   "source": [
    "design.chips['Q_chip']['size']['center_z'] = '10 um'\n",
    "design.chips['Q_chip']['size']['center_z']"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5f8e095c",
   "metadata": {},
   "source": [
    "It is possible that you would like to assign a new material to the chip substrate. In this case, I'd usually define a new material in the library instead of modifying the existing one. If this is not of interest, feel free to skip this part.\n",
    "\n",
    "Say, we would like to have a Silicon substrate with a different dielectric constant (11.45 instead of the default value of 11.9). Let's call this new material 'Si_11.45'.\n",
    "\n",
    "To do this, first we add the new material to the ANSYS material library (either manually or scripted like what we did below), and then specify the new material in the design object."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "025e0bfa",
   "metadata": {},
   "outputs": [],
   "source": [
    "# new material properties\n",
    "newMaterial_name = 'Si_11.45'\n",
    "newMaterial_permittivity = '11.45'\n",
    "newMaterial_losstangent = '1e-7'"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6eb99015",
   "metadata": {},
   "outputs": [],
   "source": [
    "# add the new material via scripting\n",
    "# uncomment if needed\n",
    "from pyEPR import ansys, project_info\n",
    "# get the handles to the ANSYS system\n",
    "ans_prj = project_info.ProjectInfo()\n",
    "oProject = ans_prj.project._project\n",
    "defmanager = oProject.GetDefinitionManager()\n",
    "# check if the material exists\n",
    "if not defmanager.DoesMaterialExist(newMaterial_name):\n",
    "    defmanager.AddMaterial(\n",
    "        [\n",
    "            \"NAME:%s\"%(newMaterial_name),\n",
    "            \"CoordinateSystemType:=\", \"Cartesian\",\n",
    "            \"BulkOrSurfaceType:=\", 1,\n",
    "            [\n",
    "                    \"NAME:PhysicsTypes\",\n",
    "                    \"set:=\", [\"Electromagnetic\"]\n",
    "            ],\n",
    "            \"permittivity:=\", \"%s\"%(newMaterial_permittivity),\n",
    "            \"dielectric_loss_tangent:=\", \"%s\"%(newMaterial_losstangent)\n",
    "        ])\n",
    "# release the handle to ANSYS\n",
    "ans_prj.project.release()\n",
    "ans_prj.desktop.release()\n",
    "ans_prj.app.release()\n",
    "ansys.release()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1b1af6d6",
   "metadata": {},
   "outputs": [],
   "source": [
    "# Specify the new material assigment for the chip\n",
    "design.chips['C_chip']['material'] = newMaterial_name\n",
    "design.chips['Q_chip']['material'] = newMaterial_name"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2493e788",
   "metadata": {},
   "source": [
    "## 3.  Run EPR Analysis\n",
    "We proceed to run the EPR analysis. This follows closely tutorial 4.02 Eigenmode and EPR.\n",
    "\n",
    "First, we initialise an EPRanalysis class object, and update the ANSYS simulation setup."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "548873c3",
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.analyses.quantization import EPRanalysis\n",
    "eig_fc = EPRanalysis(design, \"hfss\")\n",
    "eig_fc.sim.setup"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ac123d75",
   "metadata": {},
   "outputs": [],
   "source": [
    "# update setup setting\n",
    "eig_fc.sim.setup.max_passes = 20\n",
    "eig_fc.sim.setup.vars.Lj = '10 nH'\n",
    "# since we are analysing both the qubit and the resonator, we set the number of modes to be 2\n",
    "eig_fc.sim.setup.n_modes = 2\n",
    "# if there is not enough computational power, you can set a less stringent max_delta_f\n",
    "eig_fc.sim.setup.max_delta_f = 1 \n",
    "eig_fc.sim.setup.min_freq_ghz = 1.5\n",
    "# pass the name of the junction (for the EPR analysis purpose)\n",
    "eig_fc.setup.junctions.jj.rect = 'JJ_rect_Lj_Q1_rect_jj'\n",
    "eig_fc.setup.junctions.jj.line = 'JJ_Lj_Q1_rect_jj_'\n",
    "\n",
    "eig_fc.sim.setup"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "32351948",
   "metadata": {},
   "source": [
    "Next, we run the ANSYS simulation and then the EPR analysis."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "491db648",
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_fc.sim.run(name=\"qubitres\", components=['Q1', 'R1'], open_terminations=[], box_plus_buffer = True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b973d2bc",
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_fc.setup.dissipatives.dielectrics_bulk = ['Q_chip', 'C_chip']\n",
    "eig_fc.run_epr()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "6f56cc50",
   "metadata": {},
   "outputs": [],
   "source": [
    "eig_fc.sim.close()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "pymetal",
   "language": "python",
   "name": "pymetal"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
